home *** CD-ROM | disk | FTP | other *** search
- #! /usr/bin/python
- #
- # Licensed under the MIT license
- # http://opensource.org/licenses/mit-license.php
-
- # Copyright 2006,2007,2008 Frank Scholz <coherence@beebits.net>
-
- """ Coherence is a framework to host DLNA/UPnP devices
-
- For more information about it and its available backends
- point your browser to: http://coherence.beebits.net
- """
-
- import os, sys
-
- import string
-
- from twisted.python import usage, text
-
-
- from coherence import __version__
-
- from coherence.extern.simple_config import Config,ConfigItem
-
- """
- thankfully taken from twisted.scripts._twistd_unix.py
- """
- def daemonize():
- # See http://www.erlenstar.demon.co.uk/unix/faq_toc.html#TOC16
- if os.fork(): # launch child and...
- os._exit(0) # kill off parent
- os.setsid()
- if os.fork(): # launch child and...
- os._exit(0) # kill off parent again.
- os.umask(077)
- null=os.open('/dev/null', os.O_RDWR)
- for i in range(3):
- try:
- os.dup2(null, i)
- except OSError, e:
- if e.errno != errno.EBADF:
- raise
- os.close(null)
-
- """
- taken with minor adjustments from twisted.python.text.py
- """
- def greedyWrap(inString, width=80):
- """Given a string and a column width, return a list of lines.
-
- Caveat: I'm use a stupid greedy word-wrapping
- algorythm. I won't put two spaces at the end
- of a sentence. I don't do full justification.
- And no, I've never even *heard* of hypenation.
- """
-
- outLines = []
-
- #eww, evil hacks to allow paragraphs delimited by two \ns :(
- if inString.find('\n\n') >= 0:
- paragraphs = inString.split('\n\n')
- for para in paragraphs:
- outLines.extend(greedyWrap(para, width) + [''])
- return outLines
- inWords = inString.split()
-
- column = 0
- ptr_line = 0
- while inWords:
- column = column + len(inWords[ptr_line])
- ptr_line = ptr_line + 1
-
- if (column > width):
- if ptr_line == 1:
- # This single word is too long, it will be the whole line.
- pass
- else:
- # We've gone too far, stop the line one word back.
- ptr_line = ptr_line - 1
- (l, inWords) = (inWords[0:ptr_line], inWords[ptr_line:])
- outLines.append(string.join(l,' '))
-
- ptr_line = 0
- column = 0
- elif not (len(inWords) > ptr_line):
- # Clean up the last bit.
- outLines.append(' '.join(inWords))
- del inWords[:]
- else:
- # Space
- column = column + 1
- # next word
-
- return outLines
-
- """
- taken with minor adjustments from twisted.python.usage.py
- """
- def docMakeChunks(optList, width=80):
- """
- Makes doc chunks for option declarations.
-
- Takes a list of dictionaries, each of which may have one or more
- of the keys 'long', 'short', 'doc', 'default', 'optType'.
-
- Returns a list of strings.
- The strings may be multiple lines,
- all of them end with a newline.
- """
-
- # XXX: sanity check to make sure we have a sane combination of keys.
-
- maxOptLen = 0
- for opt in optList:
- optLen = len(opt.get('long', ''))
- if optLen:
- if opt.get('optType', None) == "parameter":
- # these take up an extra character
- optLen = optLen + 1
- maxOptLen = max(optLen, maxOptLen)
-
- colWidth1 = maxOptLen + len(" -s, -- ")
- colWidth2 = width - colWidth1
- # XXX - impose some sane minimum limit.
- # Then if we don't have enough room for the option and the doc
- # to share one line, they can take turns on alternating lines.
-
- colFiller1 = " " * colWidth1
-
- optChunks = []
- seen = {}
- for opt in optList:
- if opt.get('short', None) in seen or opt.get('long', None) in seen:
- continue
- for x in opt.get('short', None), opt.get('long', None):
- if x is not None:
- seen[x] = 1
-
- optLines = []
- comma = " "
- if opt.get('short', None):
- short = "-%c" % (opt['short'],)
- else:
- short = ''
-
- if opt.get('long', None):
- long = opt['long']
- if opt.get("optType", None) == "parameter":
- long = long + '='
-
- long = "%-*s" % (maxOptLen, long)
- if short:
- comma = ","
- else:
- long = " " * (maxOptLen + len('--'))
-
- if opt.get('optType', None) == 'command':
- column1 = ' %s ' % long
- else:
- column1 = " %2s%c --%s " % (short, comma, long)
-
- if opt.get('doc', ''):
- doc = opt['doc'].strip()
- else:
- doc = ''
-
- if (opt.get("optType", None) == "parameter") \
- and not (opt.get('default', None) is None):
- doc = "%s [default: %s]" % (doc, opt['default'])
-
- if (opt.get("optType", None) == "parameter") \
- and opt.get('dispatch', None) is not None:
- d = opt['dispatch']
- if isinstance(d, usage.CoerceParameter) and d.doc:
- doc = "%s. %s" % (doc, d.doc)
-
- if doc:
- column2_l = greedyWrap(doc, colWidth2)
- else:
- column2_l = ['']
-
- optLines.append("%s%s\n" % (column1, column2_l.pop(0)))
-
- for line in column2_l:
- optLines.append("%s%s\n" % (colFiller1, line))
-
- optChunks.append(''.join(optLines))
-
- return optChunks
-
- usage.docMakeChunks = docMakeChunks
-
- def setConfigFile():
- def findConfigDir():
- try:
- configDir = os.path.expanduser('~')
- except:
- configDir = os.getcwd()
- return configDir
-
- return os.path.join( findConfigDir(), '.coherence')
-
-
- class Options(usage.Options):
-
- optFlags = [['daemon','d', 'daemonize'],
- ['noconfig', None, 'ignore any configfile found'],
- ['version','v', 'print out version']
- ]
- optParameters = [['configfile', 'c', setConfigFile(), 'configfile'],
- ['logfile', 'l', None, 'logfile'],
- ['option', 'o', None, 'activate option'],
- ['plugin', 'p', None, 'activate plugin'],
- ]
-
- def __init__(self):
- usage.Options.__init__(self)
- self['plugins'] = []
- self['options'] = {}
-
- def opt_version(self):
- print "Coherence version:", __version__
- sys.exit(0)
-
- def opt_help(self):
- sys.argv.remove('--help')
- from coherence.base import Plugins
- p = Plugins()
- for opt,doc in self.docs.items():
- if opt == 'plugin':
- self.docs[opt] = doc + '\n\nExample: --plugin=backend:FSStore,name:MyCoherence\n\nAvailable backends are:\n\n'
- self.docs[opt] += ', '.join(p.keys())
-
- print self.__str__()
- sys.exit(0)
-
- def opt_plugin(self,option):
- self['plugins'].append(option)
-
- def opt_option(self,option):
- try:
- key,value = option.split(':')
- self['options'][key] = value
- except:
- pass
-
- def main(config):
-
- from coherence.base import Coherence
- c = Coherence(config)
- #c = Coherence(plugins={'FSStore': {'content_directory':'tests/content'},
- # 'Player': {})
- #c.add_plugin('FSStore', content_directory='tests/content', version=1)
-
- if __name__ == '__main__':
-
- options = Options()
- try:
- options.parseOptions()
- except usage.UsageError, errortext:
- print '%s: %s' % (sys.argv[0], errortext)
- print '%s: Try --help for usage details.' % (sys.argv[0])
- sys.exit(0)
-
- if options['daemon'] == 1:
- daemonize()
-
- config = {}
-
- if options['noconfig'] != 1:
- try:
- config = Config(options['configfile'],root='config').config
- except SyntaxError:
- import traceback
- #print traceback.format_exc()
- try:
- from configobj import ConfigObj
- config = ConfigObj(options['configfile'])
- except:
- print "hmm, seems we are in trouble reading in any sort of config file"
- print traceback.format_exc()
- except IOError:
- print "no config file %r found" % options['configfile']
- pass
-
- for k,v in options['options'].items():
- config[k] = v
-
-
- if options['logfile'] != None:
- if isinstance(config,ConfigItem):
- config['logging'] = {}
- config['logging']['logfile'] = options['logfile']
- else:
- config['logfile'] = options['logfile']
-
- if options['daemon'] == 1:
- if options['logfile'] == None:
- if isinstance(config,ConfigItem):
- config.get('logging').get('level','none')
- else:
- config.set('logmode','none')
-
- #print config
-
- if(config.get('use_dbus', 'no') == 'yes' or
- config.get('glib', 'no') == 'yes' or
- config.get('transcoding', 'no') == 'yes'):
- try:
- from twisted.internet import glib2reactor
- glib2reactor.install()
- except AssertionError:
- print "error installing glib2reactor"
-
- if len(options['plugins']) > 0:
- plugins = config.get('plugin')
- if isinstance(plugins,dict):
- config['plugin']=[plugins]
- if plugins is None:
- plugins = config.get('plugins',None)
- if plugins == None:
- config['plugin'] = []
- plugins = config['plugin']
-
- while len(options['plugins']) > 0:
- p = options['plugins'].pop()
- plugin = {}
- plugin_conf = p.split(',')
- for pair in plugin_conf:
- pair = pair.split(':',1)
- if len(pair) == 2:
- pair[0] = pair[0].strip()
- if pair[0] in plugin:
- if not isinstance(plugin[pair[0]],list):
- new_list = [plugin[pair[0]]]
- plugin[pair[0]] = new_list
- plugin[pair[0]].append(pair[1])
- else:
- plugin[pair[0]] = pair[1]
- try:
- plugins.append(plugin)
- except AttributeError:
- print "mixing commandline plugins and configfile does not work with the old config file format"
-
-
- from twisted.internet import reactor
-
- reactor.callWhenRunning(main, config)
- reactor.run()
-